/*
 ============================================================================
 Name        : fFile.cpp
 Author      :
 Version     :
 Copyright   : Your copyright notice
 Description : CfFile implementation
 ============================================================================
 */
#include <libc\string.h>
#include <BAUTILS.H>
#include "fFile.h"
#include <aknenv.h>
#include <eikenv.h>
#include <eikapp.h>

HBufC16* GetPathPtr( const char* szPath, int *pErrorCode )
{
    int stringLength = User::StringLength( ( const unsigned char* ) szPath );
    HBufC8* filePath = HBufC8::NewL( stringLength );
    if( !filePath )
    {
        if( pErrorCode )
        {
            *pErrorCode = fFile::f_FILE_MEMORYFAILED;
        }
        return NULL;
    }

    TPtr8 filePathPtr = filePath->Des();
    filePathPtr.Copy( ( unsigned char* ) szPath, stringLength );
    HBufC16* filePath16 = HBufC16::NewL( stringLength );
    if( !filePath16 )
    {
        if( pErrorCode )
        {
            *pErrorCode = fFile::f_FILE_MEMORYFAILED;
        }
        delete filePath;
        return NULL;
    }

    TPtr16 filePathPtr16 = filePath16->Des();
    filePathPtr16.Copy( filePathPtr );
    delete filePath;

    return filePath16;
}

int fFile::ReadInt( const TDesC& aPath, TInt aPosition, int nShareMode )
{
    HBufC8* temp = fFile::Read( aPath, aPosition, sizeof(TInt), nShareMode );
    if( temp )
    {
        TInt value;
        memcpy( &value, temp->Ptr(), sizeof(TInt) );
        delete temp;
        return value;
    }
    return -1;
}

TBool fFile::IsDriveEExist()
{
    /*
     #ifdef __WINS__
     return ETrue;
     #else
     RFs fsSesson;
     User::LeaveIfError(fsSesson.Connect());
     TBool bIsExist = EFalse;

     _LIT( KEImages, "E:\\images\\" );
     bIsExist = BaflUtils::FolderExists( fsSesson, KEImages );
     fsSesson.Close();
     return bIsExist;
     #endif
     */

    RFs fsSesson;
    User::LeaveIfError( fsSesson.Connect() );
    RFile file;
    _LIT( kTestFile, "e:\\__test___.dat" );
    int result = file.Create( fsSesson, kTestFile, EFileShareAny | EFileRead );
    file.Close();
    fsSesson.Close();
    if( result == KErrNone || result == KErrAlreadyExists )
    {
        fFile::DeleteFile( kTestFile );

        return ETrue;
    }
    else
    {
        return EFalse;
    }
}
HBufC8* fFile::Read( const TDesC& aPath, int nShareMode )
{
    RFs fsSesson;
    User::LeaveIfError( fsSesson.Connect() );
    RFile file;
    if( file.Open( fsSesson, aPath, nShareMode ) != KErrNone )
    {
        fsSesson.Close();
        return NULL;/*f_FILE_OPENFAILED*/
    }

    int fileSize = 0;
    if( file.Size( fileSize ) != KErrNone )
    {
        file.Close();
        fsSesson.Close();
        return NULL;
    }

    HBufC8* dataBuffer = HBufC8::NewL( fileSize );

    if( !dataBuffer )
    {
        fsSesson.Close();
        return NULL;
    }

    /*if( aPosition > 0 )
     {
     if( file.Seek( ESeekStart, aPosition ) != KErrNone )
     {
     return NULL;
     }
     }*/

    TPtr8 dataBufferPtr = dataBuffer->Des();
    if( file.Read( dataBufferPtr, fileSize ) != KErrNone )
    {
        file.Close();
        fsSesson.Close();
        delete dataBuffer;
        return NULL;
    }
    file.Close();
    fsSesson.Close();
    return dataBuffer;
}

HBufC8* fFile::Read( const TDesC& aPath, TInt aPosition, int aLength, int nShareMode )
{
    RFs fsSesson;
    User::LeaveIfError( fsSesson.Connect() );
    RFile file;
    if( file.Open( fsSesson, aPath, nShareMode ) != KErrNone )
    {
        fsSesson.Close();
        return NULL;/*f_FILE_OPENFAILED*/
    }

    HBufC8* dataBuffer = HBufC8::NewL( aLength );

    if( !dataBuffer )
    {
        fsSesson.Close();
        return NULL;
    }
    if( aPosition > 0 )
    {
        if( file.Seek( ESeekStart, aPosition ) != KErrNone )
        {
            return NULL;
        }
    }

    TPtr8 dataBufferPtr = dataBuffer->Des();
    if( file.Read( dataBufferPtr, aLength ) != KErrNone )
    {
        file.Close();
        fsSesson.Close();
        delete dataBuffer;
        return NULL;
    }
    file.Close();
    fsSesson.Close();
    return dataBuffer;
}

int fFile::Read( const TDesC& aPath, int aLength, TDes8& aBuffer, int nShareMode )
{
    RFs fsSesson;
    User::LeaveIfError( fsSesson.Connect() );
    RFile file;
    if( file.Open( fsSesson, aPath, nShareMode ) != KErrNone )
    {
        fsSesson.Close();
        return f_FILE_OPENFAILED;
    }

    if( file.Read( aBuffer, aLength ) != KErrNone )
    {
        file.Close();
        fsSesson.Close();
        return f_FILE_READFAILED;
    }
    file.Close();
    fsSesson.Close();
    return aBuffer.Length();
}
#define min(a,b) (((a) < (b)) ? (a) : (b))
int fFile::Write( const TDesC& aPath, int aLength, const TDesC8& aBuffer, int nShareMode )
{
    RFs& fsSesson = CEikonEnv::Static()->FsSession();
    TInt ret = fsSesson.MkDirAll( aPath );
    if( ret == KErrNone || ret == KErrAlreadyExists )
    {
        //User::LeaveIfError(fsSesson.Connect());
        RFile file;
        if( file.Replace( fsSesson, aPath, nShareMode ) != KErrNone )
        {
            fsSesson.Close();
            return f_FILE_REPLACEFAILED;
        }

        if( file.SetSize( 0 ) != KErrNone )
        {
            file.Close();
            fsSesson.Close();
            return f_FILE_SETSIZEFAILED;
        }

        int nMinLength = min(aBuffer.Length(), aLength);
        if( file.Write( aBuffer, nMinLength ) != KErrNone )
        {
            file.Close();
            fsSesson.Close();
            return f_FILE_WRITEFAILED;
        }
        file.Close();
        return nMinLength;
    }
    return -1;
}

/*int fFile::Write( const TDesC& aPath, const TDesC8& aBuffer, int nShareMode )
 {
 int error_code = Write(aPath,aBuffer,aBuffer.Length(), nShareMode );
 return error_code;
 }*/

int fFile::Append( const TDesC& aPath, int aLength, const TDesC8& aBuffer, int nShareMode )
{
    RFs& fsSesson = CEikonEnv::Static()->FsSession();
    
    TInt ret = fsSesson.MkDirAll( aPath );
    if( ret == KErrNone || ret == KErrAlreadyExists )
    {
        RFile file;
        if( file.Open( fsSesson, aPath, nShareMode ) != KErrNone )
        {
            if( file.Replace( fsSesson, aPath, nShareMode ) != KErrNone )
            {
                fsSesson.Close();
                return f_FILE_REPLACEFAILED;
            }
        }

        int nPosition = 0;
        if( file.Seek( ESeekEnd, nPosition ) != KErrNone )
        {
            file.Close();
            fsSesson.Close();
            return f_FILE_SEEKFAILED;
        }

        int nMinLength = min(aBuffer.Length(), aLength);
        if( file.Write( aBuffer, nMinLength ) != KErrNone )
        {
            file.Close();
            fsSesson.Close();
            return f_FILE_WRITEFAILED;
        }
        file.Close();
        return nMinLength;
    }

    return -1;
}

int fFile::Append( const TDesC& aPath, const TDesC8& aBuffer, int nShareMode )
{
    int error_code = Append( aPath, aBuffer.Length(), aBuffer, nShareMode );
    return error_code;
}

int fFile::GetLength( const TDesC& aPath, int nShareMode )
{
    RFs fsSesson;
    User::LeaveIfError( fsSesson.Connect() );
    RFile file;
    if( file.Open( fsSesson, aPath, nShareMode ) != KErrNone )
    {
        fsSesson.Close();
        return f_FILE_OPENFAILED;
    }
    int fileSize = 0;
    if( file.Size( fileSize ) != KErrNone )
    {
        file.Close();
        fsSesson.Close();
        return f_FILE_GETSIZEFAILED;
    }

    file.Close();
    fsSesson.Close();
    return fileSize;
}
int fFile::DeleteFile( const TDesC& aPath )
{
    RFs fsSesson;
    User::LeaveIfError( fsSesson.Connect() );
    int errorCode = fsSesson.Delete( aPath );
    fsSesson.Close();
    if( errorCode != KErrNone )
    {
        return f_FILE_DELETEFAILED;
    }
    return 1;
}

int fFile::Read( const char* szPath, int nLength, unsigned char* lpBuffer, int nShareMode )
{
    HBufC8* fileData = HBufC8::NewL( nLength );
    if( !fileData )
    {
        return f_FILE_MEMORYFAILED;
    }
    TPtr8 fileDataPtr = fileData->Des();

    int errorCode = 0;
    HBufC16* filePath = GetPathPtr( szPath, &errorCode );
    if( !filePath )
    {
        delete fileData;
        return f_FILE_MEMORYFAILED;
    }
    TPtr16 filePathPtr = filePath->Des();
    memset( lpBuffer, 0, nLength );
    errorCode = Read( filePathPtr, nLength, fileDataPtr, nShareMode );

    if( errorCode > 0 )
    {
        memcpy( lpBuffer, fileDataPtr.Ptr(), errorCode );
    }
    delete filePath;
    delete fileData;
    //
    return errorCode;
}
int fFile::Write( const char* szPath, int nLength, unsigned char* lpBuffer, int nShareMode )
{
    HBufC8* fileData = HBufC8::NewL( nLength );
    if( !fileData )
    {
        return f_FILE_MEMORYFAILED;
    }
    TPtr8 fileDataPtr = fileData->Des();
    fileDataPtr.Copy( ( unsigned char* ) lpBuffer, nLength );

    int errorCode = 0;
    HBufC16* filePath = GetPathPtr( szPath, &errorCode );
    if( !filePath )
    {
        delete fileData;
        return f_FILE_MEMORYFAILED;
    }
    TPtr16 filePathPtr = filePath->Des();

    errorCode = Write( filePathPtr, nLength, fileDataPtr, nShareMode );

    delete filePath;
    delete fileData;

    return errorCode;
}
int fFile::Write( const char* szPath, unsigned char* szBuffer, int nShareMode )
{
    return Write( szPath, User::StringLength( szBuffer ), szBuffer, nShareMode );
}

int fFile::GetLength( const char* szPath, int nShareMode )
{
    int errorCode = 0;
    HBufC16* filePath = GetPathPtr( szPath, &errorCode );
    if( !filePath )
    {
        return f_FILE_MEMORYFAILED;
    }
    TPtr16 filePathPtr = filePath->Des();
    errorCode = GetLength( filePathPtr, nShareMode );
    delete filePath;

    return errorCode;
}

int fFile::DeleteFile( const char* szPath )
{
    int errorCode = 0;
    HBufC16* filePath = GetPathPtr( szPath, &errorCode );
    if( !filePath )
    {
        return f_FILE_MEMORYFAILED;
    }
    TPtr16 filePathPtr = filePath->Des();

    errorCode = DeleteFile( filePathPtr );

    delete filePath;
    return errorCode;
}

int fFile::Append( const char* szPath, unsigned char* szString, int nShareMode )
{
    return Append( szPath, User::StringLength( szString ), szString, nShareMode );
}

int fFile::Append( const char* szPath, int nLength, unsigned char* lpBuffer, int nShareMode )
{
    HBufC8* fileData = HBufC8::NewL( nLength );
    if( !fileData )
    {
        return f_FILE_MEMORYFAILED;
    }
    TPtr8 fileDataPtr = fileData->Des();
    fileDataPtr.Copy( lpBuffer, nLength );

    int errorCode = 0;
    HBufC16* filePath = GetPathPtr( szPath, &errorCode );
    if( !filePath )
    {
        delete fileData;
        return f_FILE_MEMORYFAILED;
    }
    TPtr16 filePathPtr = filePath->Des();
    errorCode = Append( filePathPtr, nLength, fileDataPtr, nShareMode );

    delete filePath;
    delete fileData;

    return errorCode;
}

int fFile::Read( const TDesC& aPath, int aLength, TDes& aBuffer, int nShareMode )
{
    HBufC8* text = HBufC8::NewL( aLength );
    TPtr8 ptr = text->Des();
    aLength = fFile::Read( aPath, aLength, ptr, nShareMode );
    aBuffer.Copy( *text );
    delete text;
    return aLength;
}

HBufC* fFile::ReadTextToUnicode( const TDesC &aPath, fTextConverter::TCharSet aCharSet, int nShareMode )
{
    if( aPath.Length() == 0 )
    {
        return NULL;
    }

    // get file length
    TInt fileLength = fFile::GetLength( aPath );
    if( fileLength < 1 )
    {
        return NULL;
    }

    // alloc the buffer for the  text, and read content as binary data
    HBufC8* temp = HBufC8::NewL( fileLength );
    if( !temp )
    {
        return NULL;
    }
    TPtr8 ptr = temp->Des();
    if( fFile::Read( aPath, fileLength, ptr, nShareMode ) < 1 )
    {
        // read failed
        delete temp;
        return NULL;
    }

    // convert to Unicode
    HBufC* text = fTextConverter::ConvertToUnicode( ptr, aCharSet );
    delete temp;
    if( text == NULL )
    {
        return NULL;
    }
    return text;
}
